Enemy NPC Tutorial
This guide borrows material from the excellent Town NPC Tutorial. This guide will show you how to create an enemy NPC Enemy NPC's should take and receive damage, drop loot and have a method of spawning. Let's see if we can cover all these things... Make Your Mod Folder As always, start by creating a mob folder or picking a pre-existing folder to use - see here for more details. The examples mob and defaults package also serve as good references. Create a folder called "NPC" within your mod folder. Create the INI file Create a text file in your NPC folder called "NPCName.ini", substituting the desired name for your NPC for 'NPCName'. You must use this same name for all the files related to this NPC, and it will be the default name displayed in game, so give this some thought. My file is called 'Evil Guide.ini'. The .ini file will contain your NPC's basic stats. It is generally a good idea to start by copying the stats of a default NPC and then customizing them. I start by taking the Guide's stats: Stats npcSlots=1 width=18 height=40 type=22 aiStyle=7 timeLeft=750 damage=10 defense=15 soundHit=1 soundKilled=1 lifeMax=250 scale=1 townNPC=True friendly=True Immunities Confused=True I then tweak the stats a bit to make him a little more unfriendly: Stats npcSlots=1 frameCount=16 animationType=28 width=18 height=40 type=-1 aiStyle=3 timeLeft=750 damage=10 defense=15 soundHit=1 soundKilled=1 lifeMax=250 scale=1 value=1000 Drops 1-3 Acorn=50 Some notes: *'frameCount' is the number of frames that are in your .png sprite image. *'aiStyle' affects how the NPC will behave. 7 is the Town NPC style. 3 is the standard "Fighter" AI, used by Zombies, Mummies, Skeletons, etc. AI Style List. *'animationType' determines the internal code used to handle animations. Very often you'll want to make a sprite that is based off of an existing one, and use the same animation code that is already built into the game, instead of going through the process of making new animation code. *'Damage', 'defense' and 'lifeMax' are self-explanatory, but important for an enemy. Surprisingly, the Guide would be damaging us if he weren't friendly, so let's go with those values for now. *'townNPC' and 'friendly' are obviously unwanted in an enemy. "Friendly", to clarify, does not affect AI behavior, only whether the player will take damage from touching the NPC and whether they can be damaged by the player. *'type' determines, primarily, what graphics will represent the NPC. This can help you locate a particular NPC's graphics in the game files, if you're looking for it (the Guide is 22). Setting type to -1 will force the NPC to use custom graphics which you will provide. This file should be called "NPCName.png" (Files MUST be PNG), and placed next to the .ini file in "NPC's". *'Value' is how much money the NPC is likely to drop (T'he game appears to randomize based on this value'). The units are copper coins, so 1000 is 10 silver. *Under '[Drops]' is a list of items to drop on death. The number after the equals sign is the percentage chance to drop. WARNING: It is currently (0.21.3) not advisable to set your NPC's type to a pre-existing type (anything not -1). In some contexts (such as spawning in Tconfig), NPC's are differentiated by type, and so multiple NPC's of the same type ("Angry Bones" and others, for instance) cannot be distinguished. Trying to spawn an "Evil Guide" would result in a normal Guide. ::: NOTE ::: When changing names, remember all files need the same name. This is '''CASE SENSITIVE': Capitalization ''matters. E.g: Evil Guide.ini Evil Guide.png Evil Guide.cs ::: NOTE END ::: Required Images You need to have a sprite for the NPC (Called "Evil Guide.png"). As described above, this is true even though we intend to use the Guide's graphics. These can be obtained through the use of the XNB Exporter which is easy to use and well documented. The Guide's image is NPC_22.xnb. Of course, creating your own custom sprites is great as well. Writing Methods For Enemy Behavior Now, to tackle some more complex characteristics, we need to create some C# code. Create a text file named "NPCName.cs" in 'NPC' with everything else. If you were to try out this NPC in-game, you might notice that they simply vanish upon death. Let's fix this. We could make a particle effect appear on being hit or dying, but since the game includes gibs for the Guide, let's spawn some gore: public void NPCLoot() { Gore.NewGore(npc.position,npc.velocity,"Guide Head",1f,-1); Gore.NewGore(npc.position,npc.velocity,"Guide Arm",1f,-1); Gore.NewGore(npc.position,npc.velocity,"Guide Arm",1f,-1); Gore.NewGore(npc.position,npc.velocity,"Guide Leg",1f,-1); Gore.NewGore(npc.position,npc.velocity,"Guide Leg",1f,-1); } The 'NPCLoot()' method will be called when the NPC is killed (Though we already specified actual item drops in the .ini file). This basic code will spawn gore at the Evil Guide's location with a velocity based on his (Including the knockbock from the killing blow). The game appears to insert some randomness for us, as the gibs don't all follow the same trajectory. I'm sure this simple code could be modified, however, for more aesthetically pleasing results. The fourth and fifth arguments represent 'scale' and 'type'; they can be left alone for our purposes. Now we must deal with the images for the gore. The 'gore' graphics in the game's content folder are, to my knowledge, unorganized, so I'll save you some time: the guide's gibs are Gore_73, Gore_74 and Gore_75. Extract these as before, then move them to a new folder in your main Mod folder called 'Gore'. Name them appropriately and reference them in the code as above. 'Spawning the NPC' Now, you probably want to spawn your NPC after all this work. Natural npc spawning is handled in the SpawnNPC method: public static bool SpawnNPC(int x, int y, int playerID) { return true; } The above code should spawn your NPC naturally, with two large caveats. First, There will be no restrictions on where you find your evil guide (He will appear in all biomes). Second, and more importantly, all other NPC's may cease to spawn! For more desirable effects, you will want to fine tune the conditions under which they spawn, and make them spawn only on a certain random chance. NPC spawning is not an exact science, and there are many ways to go about it. I suggest studying mods like Omnir's Modpacks (lots of custom enemies, a good mod), and experimenting yourself. The below code will spawn an enemy on the edges of the map everywhere above the underworld.. public static bool SpawnNPC(int x, int y, int playerID) { if (!Main.playerplayerID.zoneDungeon //not in dungeon. Note that the ! means "Not" && !Main.playerplayerID.zoneJungle //not in jungle && !Main.playerplayerID.zoneMeteor //not in meteor && (Main.playerplayerID.position.X < (Main.worldSurface * 10.0)//Spawns on the left edge of the map || Main.playerplayerID.position.X > (Main.worldSurface * 190.0)) //or right edge && Main.playerplayerID.position.Y < (Main.rockLayer * 35.0)// just above the underworld. The underworld ends at *42~ && Main.rand.Next(8) 1){ //1 out of 8 chance of spawning return true; } return false; } The above code is in the style of Omnir's modpack, and is similar to what appears in the original game code. An alternate method is to define a series of booleans representing what biome the player is in. The below code is from W1K's modpack. bool nospecialbiome = !Main.playerMain.myPlayer.zoneJungle && !Main.playerMain.myPlayer.zoneEvil && !Main.playerMain.myPlayer.zoneHoly && !Main.playerMain.myPlayer.zoneMeteor && !Main.playerMain.myPlayer.zoneDungeon; // Not necessary at all to use but needed to make all this work. bool sky = nospecialbiome && ((double)y < Main.worldSurface * 0.44999998807907104); bool surface = nospecialbiome && !sky && (y <= Main.worldSurface); bool underground = nospecialbiome && !surface && (y <= Main.rockLayer); bool underworld= (y > Main.maxTilesY-190); bool cavern = nospecialbiome && !sky && !surface && !underground && !underworld && (y <= Main.rockLayer *25) && !Main.playerMain.myPlayer.zoneJungle; bool undergroundJungle = (y >= Main.rockLayer) && !underworld && (y <= Main.rockLayer *25) && Main.playerMain.myPlayer.zoneJungle; bool undergroundEvil = (y >= Main.rockLayer) && !underworld && (y <= Main.rockLayer *25) && Main.playerMain.myPlayer.zoneEvil; bool undergroundHoly = (y >= Main.rockLayer) && !underworld && (y <= Main.rockLayer *25) && Main.playerMain.myPlayer.zoneHoly; I'll bet you want to see your NPC right now though. So let's make it so we can spawn our NPC right next to us. Hopefully you've already completed the Create a Useful Item Tutorial. If not, do so now. We can use this item, Placed in your mod's 'Item' folder as suggested in the guide, to spawn our NPC: public void UseItem(Player player, int playerID) { NPC.NewNPC((int)player.position.X,(int)player.position.Y,"Evil Guide",0); } Place this code in your "ItemName.cs" file. The above will spawn the creature right on top of you. We could also use NPC.SpawnOnPlayer(), but this will specifically spawn the NPC in the manner of a boss summoning item (The NPC will appear offscreen nearby and you will receive the message "The Evil Guide has awoken!"). Create the item in-game and enjoy your NPC! Wrapping Up So, you now have an attackable, damageable, lootable NPC. There's obviously lots more that can be done, however. Spawning obviously could use refinement, and our NPC's AI leaves something to be desired (He'll just kinda walk in a direction until he hits something). Have fun exploring the possibilities! References: NPC Config AI Styles TConfig Classes Terraria NPC Class